package com.nec.recommend.module.weapp.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.nec.recommend.auth.AuthUser;
import com.nec.recommend.exception.ServiceException;
import com.nec.recommend.module.weapp.dto.WeappRecommendUserDTO;
import com.nec.recommend.module.weapp.entity.*;
import com.nec.recommend.module.weapp.mapper.WeappRecommendMapper;
import com.nec.recommend.module.weapp.service.*;
import com.nec.recommend.module.weapp.vo.WeappUserVO;
import com.nec.recommend.utils.AuthUserUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Objects;

@Service
public class WeappRecommendServiceImpl extends ServiceImpl<WeappRecommendMapper, WeappRecommend> implements WeappRecommendService {
    private final WeappUserService weappUserService;
    private final WeappScoreService weappScoreService;
    private final WeappConfigService weappConfigService;
    private final WeappUserCarInfoService weappUserCarInfoService;


    public WeappRecommendServiceImpl(WeappUserService weappUserService, WeappScoreService weappScoreService, WeappConfigService weappConfigService, WeappUserCarInfoService weappUserCarInfoService) {
        this.weappUserService = weappUserService;
        this.weappScoreService = weappScoreService;
        this.weappConfigService = weappConfigService;
        this.weappUserCarInfoService = weappUserCarInfoService;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean submitUserInfo(WeappRecommendUserDTO weappRecommendUserDTO, WeappUserVO weappUserVO) {
        WeappUser weappUser = BeanUtil.copyProperties(weappUserVO, WeappUser.class);
        AuthUser authUser = AuthUserUtils.getUser();
        weappUser.setId(authUser.getId());
        weappUser.setRecommendUserId(weappRecommendUserDTO.getUserId());
        // 更新当前用户的基本信息
        boolean updateFlag = weappUserService.updateById(weappUser);
        // 查询推荐获取积分配置
        Integer recommendScore = getRecommendScoreConfig();
        // 如果当前用户信息修改成功以及以下新增或修改都成功则返回true，否则回滚事务
        if (updateFlag &&
                // 保存意向车型记录
                this.saveUserCarInfo(weappUserVO, authUser.getId()) &&
                // 修改推荐记录状态为推荐成功以及补全被推荐人姓名
                this.updateRecommend(weappRecommendUserDTO.getShareId(), weappUser) &&
                // 累加积分
                this.incrementRecommendScore(recommendScore, weappRecommendUserDTO) &&
                // 保存积分变动明细
                this.saveScoreRecord(recommendScore, weappRecommendUserDTO, weappUserVO)) {
            // 提交成功后刷新会话中的用户信息
            BeanUtil.copyProperties(weappUser, authUser);
            weappUserService.refreshUserInfo(authUser);
            return true;
        }
        throw new ServiceException("提交失败,请重新进入分享链接重试");
    }

    private boolean saveUserCarInfo(WeappUserVO weappUserVO, Long userId) {
        WeappUserCarInfo userCarInfo = BeanUtil.copyProperties(weappUserVO, WeappUserCarInfo.class);
        userCarInfo.setUserId(userId);
        return weappUserCarInfoService.save(userCarInfo);
    }

    private Integer getRecommendScoreConfig() {
        WeappConfig weappConfig = weappConfigService.getById("recommend_score");
        if (Objects.nonNull(weappConfig)) {
            return weappConfig.getValue();
        }
        throw new ServiceException("未找到推荐获取积分配置，请联系管理员");
    }

    public boolean updateRecommend(String shareId, WeappUser weappUser) {
        WeappRecommend weappRecommend = new WeappRecommend();
        weappRecommend.setReceivedName(weappUser.getName());
        weappRecommend.setStatus(1);
        return this.update(weappRecommend, Wrappers.lambdaQuery(WeappRecommend.class).eq(WeappRecommend::getShareId, shareId).eq(WeappRecommend::getReceivedUserId, weappUser.getId()));
    }

    @Override
    public boolean saveRecommend(WeappRecommendUserDTO weappRecommendUserDTO) {
        Long userId = AuthUserUtils.getUserId();
        // 查询当前用户此分享id的推荐记录是否已经存在待提交的
        WeappRecommend recommend = this.getOne(Wrappers.lambdaQuery(WeappRecommend.class).eq(WeappRecommend::getShareId, weappRecommendUserDTO.getShareId()).eq(WeappRecommend::getUserId, userId));
        if (Objects.nonNull(recommend)) {
            if (recommend.getStatus() == 1) {
                throw new ServiceException("该分享链接您已经成功提交过了");
            }
            return true;
        }
        WeappRecommend weappRecommend = new WeappRecommend();
        weappRecommend.setName(weappRecommendUserDTO.getName());
        weappRecommend.setUserId(weappRecommendUserDTO.getUserId());
        weappRecommend.setShareId(weappRecommendUserDTO.getShareId());
        weappRecommend.setReceivedName("-");
        weappRecommend.setReceivedUserId(userId);
        weappRecommend.setRecommendTime(weappRecommendUserDTO.getRecommendTime());
        weappRecommend.setStatus(2);
        return this.save(weappRecommend);
    }

    private boolean incrementRecommendScore(Integer recommendScore, WeappRecommendUserDTO weappRecommendUserDTO) {
        // 查询推荐人当前拥有的积分
        WeappUser recommendWeappUser = weappUserService.getOne(Wrappers.lambdaQuery(WeappUser.class).select(WeappUser::getId, WeappUser::getScore, WeappUser::getMaxScore).eq(WeappUser::getId, weappRecommendUserDTO.getUserId()));
        // 累加推荐成功获取的积分
        recommendWeappUser.setScore(recommendWeappUser.getScore() + recommendScore);
        recommendWeappUser.setMaxScore(recommendWeappUser.getMaxScore() + recommendScore);
        // 修改推荐人的积分数量
        return weappUserService.updateById(recommendWeappUser);
    }

    private boolean saveScoreRecord(Integer recommendScore, WeappRecommendUserDTO weappRecommendUserDTO, WeappUserVO weappUserVO) {
        WeappScore weappScore = new WeappScore();
        weappScore.setTitle("推荐给" + weappUserVO.getName());
        weappScore.setScore(recommendScore);
        weappScore.setUserId(weappRecommendUserDTO.getUserId());
        weappScore.setStatus(1);
        weappScore.setRemark("推荐日期：" + weappRecommendUserDTO.getRecommendTime());
        return weappScoreService.save(weappScore);
    }
}
